#ifndef SH_UTILITY_THREAD_HPP
#define SH_UTILITY_THREAD_HPP

#ifdef _WIN32
#include <conio.h>
#elif defined(__linux__) || defined(__ANDROID__)
#include <unistd.h>
#include <sys/select.h>
#endif
#include <thread>
#include "../time/timestamp.hpp"

namespace sh {

template<typename T = std::chrono::milliseconds>
inline void sleep(size_t time) { std::this_thread::sleep_for(T(time)); }
inline void sleep_s(size_t time) { return sleep<std::chrono::seconds>(time); }
inline void sleep_ms(size_t time) { return sleep<std::chrono::milliseconds>(time); }


#ifdef _WIN32
inline bool waitKey(char key, long long msec) {
    auto startTime = timestamp::steady_ms();
    while (true) {
        if (_kbhit() && _getch() == key) return true;
        auto curTime = timestamp::steady_ms();
        if (curTime - startTime >= msec) break;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return false;
}
#elif defined(__linux__) || defined(__ANDROID__)
inline bool waitKey(char key, long long msec) {
    fd_set set;
    FD_ZERO(&set);
    FD_SET(STDIN_FILENO, &set);
    struct timeval timeout;
    timeout.tv_sec = 0; 
    timeout.tv_usec = 1000;
    int rv = select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout);

    if (rv > 0 && FD_ISSET(STDIN_FILENO, &set)) {
        char ch {};
        int bytesRead = read(STDIN_FILENO, &ch, 1);
        if (bytesRead > 0 && ch == key) return true;
    }

    return false;
}
#endif
}

#endif // SH_UTILITY_THREAD_HPP